package com.goldgov.ms.adapter.call;

import com.goldgov.ms.adapter.call.source.RemoteUrlSource;
import java.net.URL;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

public class RemoteCallService {
	private RestTemplate restTemplate;
	private RemoteUrlSource remoteUrlSource;
	private static final Pattern NAMES_PATTERN = Pattern.compile("\\{([^/]+?)\\}");

	public RemoteCallService(RestTemplate restTemplate, RemoteUrlSource remoteUrlSource) {
		this.restTemplate = restTemplate;
		this.remoteUrlSource = remoteUrlSource;
	}

	public <T> T getForObject(String optCode, Class<T> responseType, Map<String, ?> uriVariables) {
		String remoteUrl = this.getUrl(optCode);
		remoteUrl = this.processArrayMapVars(remoteUrl, uriVariables);
		return (T) this.restTemplate.getForObject(remoteUrl, responseType, uriVariables);
	}

	public <T> T getForObject(String optCode, Class<T> responseType, Object... uriVariables) {
		String remoteUrl = this.getUrl(optCode);
		return (T) this.restTemplate.getForObject(remoteUrl, responseType, uriVariables);
	}

	public <T> T postForObject(String optCode, Class<T> responseType, Map<String, ?> uriVariables) {
		String remoteUrl = this.getUrl(optCode);
		remoteUrl = this.processArrayMapVars(remoteUrl, uriVariables);
		return (T) this.restTemplate.postForObject(remoteUrl, null, responseType, uriVariables);
	}

	public <T> T postForObject(String optCode, Class<T> responseType, Object... uriVariables) {
		String remoteUrl = this.getUrl(optCode);
		return (T) this.restTemplate.postForObject(remoteUrl, null, responseType, uriVariables);
	}

	private String processArrayMapVars(String remoteUrl, Map<String, ?> uriVariables) {
		Matcher matcher = NAMES_PATTERN.matcher(remoteUrl);
		while (matcher.find()) {
			String varValue;
			String match = matcher.group(1);
			if (!match.endsWith("[]"))
				continue;
			String varName = match.substring(0, match.length() - 2);
			Object varValueObject = uriVariables.get(match);
			if (varValueObject.getClass().isArray()) {
				StringBuilder sb = new StringBuilder();
				Object[] valueArray = (Object[]) varValueObject;
				for (int i = 0; i < valueArray.length; ++i) {
					sb.append(varName);
					sb.append("=");
					sb.append(valueArray[i]);
					if (i >= valueArray.length - 1)
						continue;
					sb.append("&");
				}
				varValue = sb.toString();
			} else {
				varValue = varValueObject.toString();
			}
			remoteUrl = StringUtils.replace((String) remoteUrl, (String) ("{" + match + "}"), (String) varValue);
		}
		return remoteUrl;
	}

	public String getUrl(String optCode) {
		URL remoteUrl = this.remoteUrlSource.getRemoteUrl(optCode);
		if (remoteUrl == null) {
			throw new RuntimeException("url 不存在。code=" + optCode);
		}
		return remoteUrl.toString();
	}
}